package cn.bdqn.t354.config.shiro;

import cn.bdqn.t354.pojo.Right;
import cn.bdqn.t354.pojo.Role;
import cn.bdqn.t354.pojo.User;
import cn.bdqn.t354.service.RightService;
import cn.bdqn.t354.service.RoleService;
import cn.bdqn.t354.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class MyShiroRealm extends AuthorizingRealm {
    @Resource
    UserService userService;
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Resource
    RoleService roleService;
    @Resource
    RightService rightService;

    //获取授权信息
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //登录用户
        User user=(User)principalCollection.getPrimaryPrincipal();
        //静态授权
        SimpleAuthorizationInfo authorizationInfo=
                new SimpleAuthorizationInfo();
        //添加角色
//        authorizationInfo.addRole(user.getRole().getRoleName());
//        if(user.getRole().getRoleName().equals("管理员")){
//            //添加权限
//            authorizationInfo.addStringPermission("添加用户");
//            authorizationInfo.addStringPermission("修改用户");
//            authorizationInfo.addStringPermission("删除用户");
//        }
//        authorizationInfo.addStringPermission("用户列表");

        //添加角色
//        authorizationInfo.addRole(user.getRole().getRoleName());
        Role role = roleService.getRoleByUsrId(user.getUsrId());
        authorizationInfo.addRole(role.getRoleName());
        //添加权限
//        List<Right> rights = user.getRole().getRights();
        List<Right> rights = rightService.findRightsByRoleId(role.getRoleId());
        for (Right right : rights) {
            authorizationInfo.addStringPermission(right.getRightCode());
        }
        return authorizationInfo;
    }

    //获取认证的信息
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token=(UsernamePasswordToken)authenticationToken;

        //登录次数限制
        //每一个用户密码错误次数的计数器
        //规定 密码错误次数计数器：shiro_login_count_用户名

        //1. 获取密码错误次数计数器
        //如果没有 创建一个计数器 初始化1
        //如果有 计数器加1

        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        if(!"LOCK".equals(opsForValue.get("shiro_is_lock_"+token.getUsername()))){
            opsForValue.increment("shiro_login_count_" + token.getUsername(),1);

            //2. 判断密码错误次数计数器
            String count = opsForValue.get("shiro_login_count_" + token.getUsername());
            if(Integer.parseInt(count)>5){
                //锁定
                //在redis存储一个锁
                opsForValue.set("shiro_is_lock_"+token.getUsername(),
                        "LOCK",1, TimeUnit.MINUTES);
                //清空密码错误次数计数器
                stringRedisTemplate.delete("shiro_login_count_"+token.getUsername());
            }
        }

        //3. 判断有没有上锁
        if("LOCK".equals(opsForValue.get("shiro_is_lock_"+token.getUsername()))){
            throw new DisabledAccountException("账号不可用");
        }

        //构造认证信息（也就是根据传过来的用户名查询数据库）
        User user=userService.getUserByUsrName(token.getUsername());
        if(user==null){//没查询到数据；说明数据库没有该账号
            throw new UnknownAccountException("未知账号");
        }
        if(user.getUsrFlag()==0){//账号被锁定
            throw new LockedAccountException("账号被锁定");
        }
        //构造用户信息（用户名和密码组成）
        return new SimpleAuthenticationInfo(user,
                user.getUsrPassword(),
                ByteSource.Util.bytes("czkt"),getName());
    }

    /**
     * 刷新当前用户的权限缓存
     */
    public void clearMyAuthenticationInfoCache(){
        clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }

    /**
     * 刷新所有用户的权限缓存
     */
    public void clearAllAuthenticationInfoCache(){
         //判断是否开启权限缓存
         if(this.isAuthorizationCachingEnabled()){
             //获取缓存管理器
             CacheManager cacheManager = this.getCacheManager();
             if(cacheManager!=null){
                 //获取权限缓存的名称
                 String authorizationCacheName = this.getAuthorizationCacheName();
                 //获取权限缓存
                 Cache<Object, Object> cache = cacheManager.getCache(authorizationCacheName);
                 if(cache!=null){
                     cache.clear();
                 }
             }
         }
    }
}
